<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>SpringCloud | JavaKeeper</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/icon.svg">
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?a949a9b30eb86ac0159e735ff8670c03";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
            // 引入谷歌,不需要可删除这段
            var hm1 = document.createElement("script");
            hm1.src = "https://www.googletagmanager.com/gtag/js?id=UA-169923503-1";
            var s1 = document.getElementsByTagName("script")[0]; 
            s1.parentNode.insertBefore(hm1, s1);
        })();
        // 谷歌加载,不需要可删除
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-169923503-1');
    </script>
    <meta name="description" content="">
    <meta name="keywords" content="JavaKeeper,Java,Java开发,算法,blog">
    <link rel="preload" href="/assets/css/0.styles.91f57736.css" as="style"><link rel="preload" href="/assets/js/app.447d4224.js" as="script"><link rel="preload" href="/assets/js/3.9d76740c.js" as="script"><link rel="preload" href="/assets/js/1.c4fd7d2e.js" as="script"><link rel="preload" href="/assets/js/90.5202da0a.js" as="script"><link rel="prefetch" href="/assets/js/10.8cf3be2c.js"><link rel="prefetch" href="/assets/js/100.74f35ab8.js"><link rel="prefetch" href="/assets/js/101.7a062346.js"><link rel="prefetch" href="/assets/js/102.c9485235.js"><link rel="prefetch" href="/assets/js/103.d88a3805.js"><link rel="prefetch" href="/assets/js/104.6e034144.js"><link rel="prefetch" href="/assets/js/105.d22f7450.js"><link rel="prefetch" href="/assets/js/106.a6cb54b0.js"><link rel="prefetch" href="/assets/js/107.7b65e72b.js"><link rel="prefetch" href="/assets/js/108.eb5804bb.js"><link rel="prefetch" href="/assets/js/109.05f775e5.js"><link rel="prefetch" href="/assets/js/11.c54ae13c.js"><link rel="prefetch" href="/assets/js/110.51d3d641.js"><link rel="prefetch" href="/assets/js/111.022b64a7.js"><link rel="prefetch" href="/assets/js/112.da8afd52.js"><link rel="prefetch" href="/assets/js/113.05a17b18.js"><link rel="prefetch" href="/assets/js/114.8960d913.js"><link rel="prefetch" href="/assets/js/115.67919f68.js"><link rel="prefetch" href="/assets/js/116.62b0cd71.js"><link rel="prefetch" href="/assets/js/117.ebac3eff.js"><link rel="prefetch" href="/assets/js/118.ecd629bd.js"><link rel="prefetch" href="/assets/js/119.a09a0897.js"><link rel="prefetch" href="/assets/js/12.60aa3b24.js"><link rel="prefetch" href="/assets/js/120.bf639d3d.js"><link rel="prefetch" href="/assets/js/121.b89d0c8e.js"><link rel="prefetch" href="/assets/js/122.1a75ff83.js"><link rel="prefetch" href="/assets/js/123.d2127132.js"><link rel="prefetch" href="/assets/js/124.2caff9e0.js"><link rel="prefetch" href="/assets/js/125.9b9f966a.js"><link rel="prefetch" href="/assets/js/126.58cdfb3d.js"><link rel="prefetch" href="/assets/js/127.8ef09c53.js"><link rel="prefetch" href="/assets/js/128.efdc2ae4.js"><link rel="prefetch" href="/assets/js/129.e35cbc57.js"><link rel="prefetch" href="/assets/js/13.125c13a0.js"><link rel="prefetch" href="/assets/js/130.f01a55e3.js"><link rel="prefetch" href="/assets/js/131.65205f4a.js"><link rel="prefetch" href="/assets/js/132.f42c5a0a.js"><link rel="prefetch" href="/assets/js/133.9ba468b3.js"><link rel="prefetch" href="/assets/js/134.7b597ba9.js"><link rel="prefetch" href="/assets/js/135.fb828b9a.js"><link rel="prefetch" href="/assets/js/136.3887532f.js"><link rel="prefetch" href="/assets/js/137.549bae01.js"><link rel="prefetch" href="/assets/js/138.db8d423d.js"><link rel="prefetch" href="/assets/js/139.dbaf2267.js"><link rel="prefetch" href="/assets/js/14.bd1d0b0d.js"><link rel="prefetch" href="/assets/js/140.6cb65fdc.js"><link rel="prefetch" href="/assets/js/141.9bd6cc4b.js"><link rel="prefetch" href="/assets/js/142.552db5ed.js"><link rel="prefetch" href="/assets/js/143.2c9f2bf4.js"><link rel="prefetch" href="/assets/js/144.fba98a15.js"><link rel="prefetch" href="/assets/js/145.c42f3a21.js"><link rel="prefetch" href="/assets/js/146.596d4d33.js"><link rel="prefetch" href="/assets/js/147.c48ae5c1.js"><link rel="prefetch" href="/assets/js/148.71064871.js"><link rel="prefetch" href="/assets/js/149.16582d21.js"><link rel="prefetch" href="/assets/js/15.f247873b.js"><link rel="prefetch" href="/assets/js/150.ead09aca.js"><link rel="prefetch" href="/assets/js/151.971fdf4b.js"><link rel="prefetch" href="/assets/js/152.369c9362.js"><link rel="prefetch" href="/assets/js/153.371edd15.js"><link rel="prefetch" href="/assets/js/154.e090b491.js"><link rel="prefetch" href="/assets/js/155.c68bf602.js"><link rel="prefetch" href="/assets/js/156.304aea8d.js"><link rel="prefetch" href="/assets/js/157.83beef7f.js"><link rel="prefetch" href="/assets/js/158.bb1794b0.js"><link rel="prefetch" href="/assets/js/159.2d54e792.js"><link rel="prefetch" href="/assets/js/16.04336c71.js"><link rel="prefetch" href="/assets/js/160.99d56586.js"><link rel="prefetch" href="/assets/js/161.edf660aa.js"><link rel="prefetch" href="/assets/js/162.0b84606e.js"><link rel="prefetch" href="/assets/js/163.b59e0d60.js"><link rel="prefetch" href="/assets/js/164.d9eb8228.js"><link rel="prefetch" href="/assets/js/165.ca624c79.js"><link rel="prefetch" href="/assets/js/166.025b2ba1.js"><link rel="prefetch" href="/assets/js/167.abc982cc.js"><link rel="prefetch" href="/assets/js/168.27ca13dc.js"><link rel="prefetch" href="/assets/js/169.41e753a2.js"><link rel="prefetch" href="/assets/js/17.43b3c1c8.js"><link rel="prefetch" href="/assets/js/170.626319e1.js"><link rel="prefetch" href="/assets/js/171.a221dddf.js"><link rel="prefetch" href="/assets/js/172.464b2361.js"><link rel="prefetch" href="/assets/js/173.96a3afee.js"><link rel="prefetch" href="/assets/js/174.116607c2.js"><link rel="prefetch" href="/assets/js/175.ea3e8659.js"><link rel="prefetch" href="/assets/js/176.7d7b8afc.js"><link rel="prefetch" href="/assets/js/177.a6e00aa0.js"><link rel="prefetch" href="/assets/js/178.1f93afaf.js"><link rel="prefetch" href="/assets/js/179.3aa00dcd.js"><link rel="prefetch" href="/assets/js/18.d81b44d5.js"><link rel="prefetch" href="/assets/js/180.f8b2b75a.js"><link rel="prefetch" href="/assets/js/181.8e11258a.js"><link rel="prefetch" href="/assets/js/182.22243941.js"><link rel="prefetch" href="/assets/js/183.d051fdf6.js"><link rel="prefetch" href="/assets/js/184.a994075e.js"><link rel="prefetch" href="/assets/js/185.776c7e16.js"><link rel="prefetch" href="/assets/js/186.f1887955.js"><link rel="prefetch" href="/assets/js/187.da0d3626.js"><link rel="prefetch" href="/assets/js/188.8dfc358f.js"><link rel="prefetch" href="/assets/js/189.dcac5a59.js"><link rel="prefetch" href="/assets/js/19.1b3d66e1.js"><link rel="prefetch" href="/assets/js/190.c7e413d0.js"><link rel="prefetch" href="/assets/js/191.d9806121.js"><link rel="prefetch" href="/assets/js/192.869791da.js"><link rel="prefetch" href="/assets/js/193.2d74c4c8.js"><link rel="prefetch" href="/assets/js/194.c73a1909.js"><link rel="prefetch" href="/assets/js/195.e8c74834.js"><link rel="prefetch" href="/assets/js/20.bd5949ec.js"><link rel="prefetch" href="/assets/js/21.3fcf98cf.js"><link rel="prefetch" href="/assets/js/22.2fa1e2e8.js"><link rel="prefetch" href="/assets/js/23.1ae64bb4.js"><link rel="prefetch" href="/assets/js/24.7bdf7387.js"><link rel="prefetch" href="/assets/js/25.392c436e.js"><link rel="prefetch" href="/assets/js/26.58acbd4b.js"><link rel="prefetch" href="/assets/js/27.c725bdd5.js"><link rel="prefetch" href="/assets/js/28.6c9bda1e.js"><link rel="prefetch" href="/assets/js/29.e656b537.js"><link rel="prefetch" href="/assets/js/30.2c326fc7.js"><link rel="prefetch" href="/assets/js/31.e6c9fa30.js"><link rel="prefetch" href="/assets/js/32.c9c88437.js"><link rel="prefetch" href="/assets/js/33.0c53373c.js"><link rel="prefetch" href="/assets/js/34.9821e543.js"><link rel="prefetch" href="/assets/js/35.de8253eb.js"><link rel="prefetch" href="/assets/js/36.d182f929.js"><link rel="prefetch" href="/assets/js/37.9fa79014.js"><link rel="prefetch" href="/assets/js/38.9bebff76.js"><link rel="prefetch" href="/assets/js/39.19a3a2d4.js"><link rel="prefetch" href="/assets/js/4.564edb9d.js"><link rel="prefetch" href="/assets/js/40.cca6955f.js"><link rel="prefetch" href="/assets/js/41.854cd09a.js"><link rel="prefetch" href="/assets/js/42.ca7b612f.js"><link rel="prefetch" href="/assets/js/43.87027d58.js"><link rel="prefetch" href="/assets/js/44.8c2b4f4b.js"><link rel="prefetch" href="/assets/js/45.dffb4e08.js"><link rel="prefetch" href="/assets/js/46.f58049a5.js"><link rel="prefetch" href="/assets/js/47.6854070c.js"><link rel="prefetch" href="/assets/js/48.6cd9fa3d.js"><link rel="prefetch" href="/assets/js/49.e8861afa.js"><link rel="prefetch" href="/assets/js/5.5c31d62f.js"><link rel="prefetch" href="/assets/js/50.703bffab.js"><link rel="prefetch" href="/assets/js/51.6655c373.js"><link rel="prefetch" href="/assets/js/52.deb2eb09.js"><link rel="prefetch" href="/assets/js/53.6e0ed77d.js"><link rel="prefetch" href="/assets/js/54.b05c58ad.js"><link rel="prefetch" href="/assets/js/55.49c8164e.js"><link rel="prefetch" href="/assets/js/56.a5574e6b.js"><link rel="prefetch" href="/assets/js/57.58cb0de4.js"><link rel="prefetch" href="/assets/js/58.52345112.js"><link rel="prefetch" href="/assets/js/59.663ce78d.js"><link rel="prefetch" href="/assets/js/6.a9df34ee.js"><link rel="prefetch" href="/assets/js/60.f06adde2.js"><link rel="prefetch" href="/assets/js/61.170255a1.js"><link rel="prefetch" href="/assets/js/62.9d120050.js"><link rel="prefetch" href="/assets/js/63.70cced6b.js"><link rel="prefetch" href="/assets/js/64.577f3548.js"><link rel="prefetch" href="/assets/js/65.c037b29d.js"><link rel="prefetch" href="/assets/js/66.7dd1045f.js"><link rel="prefetch" href="/assets/js/67.d3aa4d6c.js"><link rel="prefetch" href="/assets/js/68.526dbb61.js"><link rel="prefetch" href="/assets/js/69.58269266.js"><link rel="prefetch" href="/assets/js/7.6609d4d6.js"><link rel="prefetch" href="/assets/js/70.64108f1b.js"><link rel="prefetch" href="/assets/js/71.1e95e0a6.js"><link rel="prefetch" href="/assets/js/72.42e7ec94.js"><link rel="prefetch" href="/assets/js/73.dad4e1c5.js"><link rel="prefetch" href="/assets/js/74.28ea286a.js"><link rel="prefetch" href="/assets/js/75.dd6d4c6f.js"><link rel="prefetch" href="/assets/js/76.ca6539df.js"><link rel="prefetch" href="/assets/js/77.feb13b0e.js"><link rel="prefetch" href="/assets/js/78.321e90e6.js"><link rel="prefetch" href="/assets/js/79.68eb8fcf.js"><link rel="prefetch" href="/assets/js/8.396d51fd.js"><link rel="prefetch" href="/assets/js/80.4edb5321.js"><link rel="prefetch" href="/assets/js/81.735d7e57.js"><link rel="prefetch" href="/assets/js/82.fa120bdf.js"><link rel="prefetch" href="/assets/js/83.bf755f94.js"><link rel="prefetch" href="/assets/js/84.9b32070c.js"><link rel="prefetch" href="/assets/js/85.592aca7c.js"><link rel="prefetch" href="/assets/js/86.4dcd9e73.js"><link rel="prefetch" href="/assets/js/87.a9e546aa.js"><link rel="prefetch" href="/assets/js/88.2a423212.js"><link rel="prefetch" href="/assets/js/89.5f455115.js"><link rel="prefetch" href="/assets/js/9.adb074c6.js"><link rel="prefetch" href="/assets/js/91.02cee99d.js"><link rel="prefetch" href="/assets/js/92.f16bad0b.js"><link rel="prefetch" href="/assets/js/93.f933634f.js"><link rel="prefetch" href="/assets/js/94.8e7b1d65.js"><link rel="prefetch" href="/assets/js/95.ee0e4a0a.js"><link rel="prefetch" href="/assets/js/96.e21d78c2.js"><link rel="prefetch" href="/assets/js/97.c87e514e.js"><link rel="prefetch" href="/assets/js/98.d123ac92.js"><link rel="prefetch" href="/assets/js/99.92d1b416.js">
    <link rel="stylesheet" href="/assets/css/0.styles.91f57736.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container no-sidebar" data-v-3ba18f14><div data-v-3ba18f14><div id="loader-wrapper" class="loading-wrapper" data-v-041fef5b data-v-3ba18f14 data-v-3ba18f14><div class="loader-main" data-v-041fef5b><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-68139a52 data-v-3ba18f14 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52>JavaKeeper</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div class="hide" data-v-3ba18f14><header class="navbar" data-v-3ba18f14><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">JavaKeeper</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask" data-v-3ba18f14></div> <aside class="sidebar" data-v-3ba18f14><div class="personal-info-wrapper" data-v-5f6acefd data-v-3ba18f14><!----> <h3 class="name" data-v-5f6acefd>
    海星
  </h3> <div class="num" data-v-5f6acefd><div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Article</h6></div> <div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Tag</h6></div></div> <hr data-v-5f6acefd></div> <nav class="nav-links"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <!----> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-68139a52 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div data-v-3ba18f14><main class="page"><div class="page-title" style="display:none;"><h1 class="title">SpringCloud</h1> <div data-v-5d8dbdb4><i class="iconfont reco-account" data-v-5d8dbdb4><span data-v-5d8dbdb4>海星</span></i> <!----> <!----> <!----></div></div> <div class="theme-reco-content content__default" style="display:none;"><h1 id="springcloud"><a href="#springcloud" class="header-anchor">#</a> SpringCloud</h1> <h2 id="微服务概述"><a href="#微服务概述" class="header-anchor">#</a> 微服务概述</h2> <h3 id="什么是微服务"><a href="#什么是微服务" class="header-anchor">#</a> 什么是微服务</h3> <ul><li>目前的微服务并没有一个统一的标准，一般是以业务来划分</li> <li>将传统的一站式应用，拆分成一个个的服务，彻底去耦合，一个微服务就是单功能业务，只做一件事。</li> <li>与微服务相对的叫巨石</li></ul> <h3 id="微服务与微服务架构"><a href="#微服务与微服务架构" class="header-anchor">#</a> 微服务与微服务架构</h3> <ul><li>微服务是一种架构模式或者一种架构风格，提倡将单一应用程序划分成一组小的服务==独立部署==，服务之间相互配合、相互协调，每个服务运行于自己的==进程==中。</li> <li>服务与服务间采用轻量级通讯，如HTTP的RESTful API等</li> <li>避免统一的、集中式的服务管理机制</li></ul> <h3 id="微服务的优缺点"><a href="#微服务的优缺点" class="header-anchor">#</a> 微服务的优缺点</h3> <h4 id="优点"><a href="#优点" class="header-anchor">#</a> 优点</h4> <ol><li>每个服务足够内聚，足够小，比较容易聚焦</li> <li>开发简单且效率高，一个服务只做一件事情</li> <li>开发团队小，一般2-5人足以（当然按实际为准）</li> <li>微服务是松耦合的，无论开发还是部署都可以独立完成</li> <li>微服务能用不同的语言开发</li> <li>易于和第三方集成，微服务允许容易且灵活的自动集成部署（持续集成工具有Jenkins,Hudson,bamboo等）</li> <li>微服务易于被开发人员理解，修改和维护，这样可以使小团队更加关注自己的工作成果，而无需一定要通过合作才能体现价值</li> <li>微服务允许你融合最新的技术</li> <li>微服务只是业务逻辑的代码，不会和HTML,CSS或其他界面组件融合。</li> <li>每个微服务都可以有自己的存储能力，数据库可自有也可以统一，十分灵活。</li></ol> <h4 id="缺点"><a href="#缺点" class="header-anchor">#</a> 缺点</h4> <ol><li>开发人员要处理分布式系统的复杂性</li> <li>多服务运维难度，随着服务的增加，运维的压力也会增大</li> <li>依赖系统部署</li> <li>服务间通讯的成本</li> <li>数据的一致性</li> <li>系统集成测试</li> <li>性能监控的难度</li></ol> <h3 id="微服务的技术栈"><a href="#微服务的技术栈" class="header-anchor">#</a> 微服务的技术栈</h3> <table><thead><tr><th style="text-align:center;">微服务条目</th> <th style="text-align:center;">落地技术</th></tr></thead> <tbody><tr><td style="text-align:center;">服务开发</td> <td style="text-align:center;">SpringBoot,Spring,SpringMVC</td></tr> <tr><td style="text-align:center;">服务配置与管理</td> <td style="text-align:center;">Netflix公司的Archaius、阿里的Diamond等</td></tr> <tr><td style="text-align:center;">服务注册与发现</td> <td style="text-align:center;">Eureka、Consul、Zookeeper等</td></tr> <tr><td style="text-align:center;">服务调用</td> <td style="text-align:center;">Rest、RPC、gRPC</td></tr> <tr><td style="text-align:center;">服务熔断器</td> <td style="text-align:center;">Hystrix、Envoy等</td></tr> <tr><td style="text-align:center;">负载均衡</td> <td style="text-align:center;">Ribbon、Nginx等</td></tr> <tr><td style="text-align:center;">服务接口调用（客户端调用服务的简化工具）</td> <td style="text-align:center;">Feign等</td></tr> <tr><td style="text-align:center;">消息队列</td> <td style="text-align:center;">Kafka、RabbitMQ、ActiveMQ等</td></tr> <tr><td style="text-align:center;">服务配置中心管理</td> <td style="text-align:center;">SpringCloudConfig、Chef等</td></tr> <tr><td style="text-align:center;">服务路由（API网关）</td> <td style="text-align:center;">Zuul等</td></tr> <tr><td style="text-align:center;">服务监控</td> <td style="text-align:center;">Zabbix、Nagios、Metrics、Specatator等</td></tr> <tr><td style="text-align:center;">全链路追踪</td> <td style="text-align:center;">Zipkin、Brave、Dapper等</td></tr> <tr><td style="text-align:center;">服务部署</td> <td style="text-align:center;">Docker、OpenStack、Kubernetes等</td></tr> <tr><td style="text-align:center;">数据流操作开发包</td> <td style="text-align:center;">SpringCloud Stream(封装与Redis，Rabbit，Kafka等发送接收消息)</td></tr> <tr><td style="text-align:center;">事件消息总线</td> <td style="text-align:center;">SpringCloud Bus</td></tr></tbody></table> <h3 id="为什么选springcloud作为微服务架构"><a href="#为什么选springcloud作为微服务架构" class="header-anchor">#</a> 为什么选SpringCloud作为微服务架构</h3> <h4 id="选型依据"><a href="#选型依据" class="header-anchor">#</a> 选型依据</h4> <ol><li>整体解决方案和框架的成熟度</li> <li>社区热度</li> <li>可维护性</li> <li>学习曲线</li></ol> <h4 id="当前各大it公司的微服务架构"><a href="#当前各大it公司的微服务架构" class="header-anchor">#</a> 当前各大IT公司的微服务架构</h4> <ol><li>阿里Dubbo/HSF</li> <li>京东JSF</li> <li>新浪Motan</li> <li>当当DubboX</li></ol> <h4 id="各微服务的框架对比"><a href="#各微服务的框架对比" class="header-anchor">#</a> 各微服务的框架对比</h4> <table><thead><tr><th style="text-align:center;">功能点/服务框架</th> <th style="text-align:center;">Netflix/SpringCloud</th> <th style="text-align:center;">Motan</th> <th style="text-align:center;">gRPC</th> <th style="text-align:center;">Thrift</th> <th style="text-align:center;">Dubbo/DubboX</th></tr></thead> <tbody><tr><td style="text-align:center;">功能定位</td> <td style="text-align:center;">完整的微服务架构</td> <td style="text-align:center;">RPC框架，但整合了ZK或Consul，实现集群环境的基本服务注册/发现</td> <td style="text-align:center;">RPC框架</td> <td style="text-align:center;">RPC框架</td> <td style="text-align:center;">服务框架</td></tr> <tr><td style="text-align:center;">支持Rest</td> <td style="text-align:center;">是，Ribbon支持多种可插拔的序列化选择</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td></tr> <tr><td style="text-align:center;">支持RPC</td> <td style="text-align:center;">否</td> <td style="text-align:center;">是</td> <td style="text-align:center;">是</td> <td style="text-align:center;">是</td> <td style="text-align:center;">是</td></tr> <tr><td style="text-align:center;">支持多语言</td> <td style="text-align:center;">是（Rest形式）</td> <td style="text-align:center;">否</td> <td style="text-align:center;">是</td> <td style="text-align:center;">是</td> <td style="text-align:center;">否</td></tr> <tr><td style="text-align:center;">服务注册/发现</td> <td style="text-align:center;">是（Eureka） Eureka服务注册表，Karyon服务端框架支持服务自注册和健康检查</td> <td style="text-align:center;">是（zookeeper/consul）</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">是</td></tr> <tr><td style="text-align:center;">负载均衡</td> <td style="text-align:center;">是（服务端zuul+客户端Ribbon） zuul-服务，动态路由 云端负载均衡  Eureka（针对中间层服务器）</td> <td style="text-align:center;">是（客户端）</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">是（客户端）</td></tr> <tr><td style="text-align:center;">配置服务</td> <td style="text-align:center;">Netflix Archaius SpringCloud Config Server集中配置</td> <td style="text-align:center;">是（zookeeper提供）</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td></tr> <tr><td style="text-align:center;">服务调用链监控</td> <td style="text-align:center;">是（zuul） Zuul提供边缘服务，API网关</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td></tr> <tr><td style="text-align:center;">高可用/容错</td> <td style="text-align:center;">是（服务端Hystrix+客户端Ribbon）</td> <td style="text-align:center;">是（客户端）</td> <td style="text-align:center;">否</td> <td style="text-align:center;">否</td> <td style="text-align:center;">是（客户端）</td></tr> <tr><td style="text-align:center;">典型应用案例</td> <td style="text-align:center;">Netflix</td> <td style="text-align:center;">Sina</td> <td style="text-align:center;">Google</td> <td style="text-align:center;">Facebook</td> <td style="text-align:center;"></td></tr> <tr><td style="text-align:center;">社区活跃度</td> <td style="text-align:center;">高</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">高</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">2017年7月才重启</td></tr> <tr><td style="text-align:center;">学习难度</td> <td style="text-align:center;">中等</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">高</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">低</td></tr> <tr><td style="text-align:center;">文档丰富度</td> <td style="text-align:center;">高</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">一般</td> <td style="text-align:center;">高</td></tr> <tr><td style="text-align:center;">其他</td> <td style="text-align:center;">Spring Cloud Bus为我们应用程序带来了更多管理端点</td> <td style="text-align:center;">支持降级</td> <td style="text-align:center;">Netflix内部在开发集成gRPC</td> <td style="text-align:center;">IDL定义</td> <td style="text-align:center;">实践公司比较多</td></tr></tbody></table> <h2 id="springcloud入门概述"><a href="#springcloud入门概述" class="header-anchor">#</a> SpringCloud入门概述</h2> <ul><li>Spring的三大模块：SpringBoot（构建），Spring Cloud（协调），Spring Cloud Data Flow（连接）</li></ul> <h3 id="springcloud是什么"><a href="#springcloud是什么" class="header-anchor">#</a> SpringCloud是什么</h3> <ul><li>分布式系统的简化版（官方介绍）</li> <li>Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具（例如配置管理，服务发现，断路器，智能路由，微代理，控制总线，一次性令牌，全局锁，领导选举，分布式会话，集群状态）。分布式系统的协调导致了样板模式, 使用Spring Cloud开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式环境中运行良好，包括开发人员自己的笔记本电脑，裸机数据中心，以及Cloud Foundry等托管平台。</li> <li>SpringCloud基于SpringBoot提供了一整套微服务的解决方案，包括服务注册与发现，配置中心，全链路监控，服务网关，负载均衡，熔断器等组件，除了基于Netflix的开源组件做高度抽象封装之外，还有一些选型中立的开源组件</li> <li>SpringCloud利用SpringBoot的开发便利性巧妙地简化了分布式系统的基础设施开发，SpringCloud为开发人员提供了快速构建分布式系统的一些工具，包括配置管理、服务发现、断路器、路由、微代理、事件总线，全局所、决策精选、分布式会话等等，他们都可以用SpringBoot的开发风格做到一键启动和部署。</li> <li>一句话概括：<strong>SpringCloud是分布式微服务架构下的一站式解决方案，是各个微服务架构落地技术的几何体，俗称微服务全家桶</strong></li></ul> <h3 id="springcloud和springboot的关系"><a href="#springcloud和springboot的关系" class="header-anchor">#</a> SpringCloud和SpringBoot的关系</h3> <p>SpringBoot：专注于快速方便的开发单个个体微服务（关注微观）</p> <p>SpringCloud：关注全局的微服务协调治理框架，将SpringBoot开发的一个个单体微服务组合并管理起来（关注宏观）</p> <ul><li>SpringBoot可以离开SpringCloud独立使用，但是SpringCloud不可以离开SpringBoot，属于依赖关系</li></ul> <h3 id="dubbo是怎么到springcloud的-哪些优缺点去技术选型"><a href="#dubbo是怎么到springcloud的-哪些优缺点去技术选型" class="header-anchor">#</a> Dubbo是怎么到SpringCloud的？哪些优缺点去技术选型</h3> <h4 id="目前成熟都互联网架构-分布式-服务治理dubbo"><a href="#目前成熟都互联网架构-分布式-服务治理dubbo" class="header-anchor">#</a> 目前成熟都互联网架构（分布式+服务治理Dubbo）</h4> <p><img src="https://imgkr.cn-bj.ufileos.com/2d7f0130-7cf0-4373-8853-8a52ccaf870a.png" alt="目前成熟都互联网架构（分布式+服务治理Dubbo）"></p> <h4 id="对比"><a href="#对比" class="header-anchor">#</a> 对比</h4> <table><thead><tr><th></th> <th style="text-align:center;">Dubbo</th> <th style="text-align:center;">Spring</th></tr></thead> <tbody><tr><td>服务注册中心</td> <td style="text-align:center;">Zookeeper</td> <td style="text-align:center;">Spring Cloud Netfilx Eureka</td></tr> <tr><td>服务调用方式</td> <td style="text-align:center;">RPC</td> <td style="text-align:center;">REST API</td></tr> <tr><td>服务监控</td> <td style="text-align:center;">Dubbo-monitor</td> <td style="text-align:center;">Spring Boot Admin</td></tr> <tr><td>断路器</td> <td style="text-align:center;">不完善</td> <td style="text-align:center;">Spring Cloud Netflix Hystrix</td></tr> <tr><td>服务网关</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Netflix Zuul</td></tr> <tr><td>分布式配置</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Config</td></tr> <tr><td>服务跟踪</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Sleuth</td></tr> <tr><td>消息总线</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Bus</td></tr> <tr><td>数据流</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Stream</td></tr> <tr><td>批量任务</td> <td style="text-align:center;">无</td> <td style="text-align:center;">Spring Cloud Task</td></tr></tbody></table> <p><strong>最大区别：</strong></p> <ul><li>Spring Cloud抛弃了RPC通讯，采用基于HTTP的REST方式。Spring Cloud牺牲了服务调用的性能，但是同时也避免了原生RPC带来的问题。REST比RPC更为灵活，不存在代码级别的强依赖，在强调快速演化的微服务环境下，显然更合适。</li> <li>==一句话：Dubbo像组装机，Spring Cloud像一体机==</li> <li>社区的支持与力度：Dubbo曾经停运了5年，虽然重启了，但是对于技术发展的新需求，还是需要开发者自行去拓展，对于中小型公司，显然显得比较费时费力，也不一定有强大的实力去修改源码</li></ul> <p>####总结</p> <ol><li>解决的问题域不一样：Dubbo的定位是一款RPC框架，Spring Cloud的目标是微服务架构下的一站式解决方案</li></ol> <h3 id="springcloud的参考资料"><a href="#springcloud的参考资料" class="header-anchor">#</a> SpringCloud的参考资料</h3> <h2 id="构建springcloud工程"><a href="#构建springcloud工程" class="header-anchor">#</a> 构建SpringCloud工程</h2> <p>概述：SpringCloud工程由一个父工程和若干个Module组成</p> <p>应该遵循的条件：约定 &gt; 配置 &gt; 编码</p> <h3 id="resttemplate类"><a href="#resttemplate类" class="header-anchor">#</a> RestTemplate类</h3> <h4 id="介绍"><a href="#介绍" class="header-anchor">#</a> 介绍</h4> <p>RestTemplate是Spring提供的用于访问Rest服务的客户端模板工具集，提供了多种远程访问Http的方法</p> <h4 id="意义"><a href="#意义" class="header-anchor">#</a> 意义</h4> <p>在一些不涉及实现方法的模块中（消费者），只需要调用其他服务暴露出的接口即可满足的需求，使用RestTemplate类中的方法可以发出需要的HTTP请求并得到返回结果。（类似Ajax）</p> <h4 id="resttemplate用法"><a href="#resttemplate用法" class="header-anchor">#</a> RestTemplate用法</h4> <div class="language-java extra-class"><pre class="language-java"><code><span class="token class-name">RestTemplate</span> restTemplate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RestTemplate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//url:请求地址</span>
<span class="token comment">//requestMap:请求参数</span>
<span class="token comment">//type.class:HTTP响应转换成的对象类型</span>
restTemplate<span class="token punctuation">.</span><span class="token function">getForObject</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span>type<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
restTemplate<span class="token punctuation">.</span><span class="token function">postForObject</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span>requestMap<span class="token punctuation">,</span>type<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h3 id="构建父工程"><a href="#构建父工程" class="header-anchor">#</a> 构建父工程</h3> <ul><li>创建一个Maven父工程并命名GAV</li> <li>打包方式为<strong>POM</strong></li> <li>在pom.xml中定义各依赖的版本号（若Module中pom.xml的依赖没有指定版本号，则会根据父工程的版本号加入依赖）</li> <li>加入通用的依赖和插件</li></ul> <h3 id="构建module"><a href="#构建module" class="header-anchor">#</a> 构建Module</h3> <ul><li>在父工程下新建Maven的Module，打包方式为jar</li> <li>一般来时GAV中 GV随父工程，自己定义A即可</li> <li>在该Module下pom.xml中加入其它需要的依赖</li> <li>正常开发即可</li> <li>完成后先clean一下Maven项目，然后再install提供给其它模块调用</li></ul> <h4 id="添加其它module的依赖方法"><a href="#添加其它module的依赖方法" class="header-anchor">#</a> 添加其它Module的依赖方法</h4> <ul><li>直接引用其GAV即可</li></ul> <div class="language-xml extra-class"><pre class="language-xml"><code>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.lzl<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>microservice-api<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>${project.version}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h4 id="配置该module下的yml"><a href="#配置该module下的yml" class="header-anchor">#</a> 配置该module下的yml</h4> <ul><li>微服务需要独立的端口</li> <li>==微服务最重要的是取名字！！！！一定要给微服务配置一个名字！这个名字就是这个微服务对外暴露的名字！==</li> <li>配置该模块下的其它相关配置（如本例配置了mybatis）</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8001</span>

<span class="token key atrule">mybatis</span><span class="token punctuation">:</span>
  <span class="token key atrule">config-location</span><span class="token punctuation">:</span> classpath<span class="token punctuation">:</span>mybatis/mybatis.cfg.xml
  <span class="token key atrule">type-aliases-package</span><span class="token punctuation">:</span> com.XXX.entity
  <span class="token key atrule">mapper-locations</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> classpath<span class="token punctuation">:</span>mybatis/mapper/<span class="token important">**/*.xml</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>dept   <span class="token comment">#为这个服务取名，非常重要！！！！！</span>
  <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> com.alibaba.druid.pool.DruidDataSource
    <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> org.gjt.mm.mysql.Driver
    <span class="token key atrule">url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//localhost<span class="token punctuation">:</span>3306/cloudDB01
    <span class="token key atrule">username</span><span class="token punctuation">:</span> root
    <span class="token key atrule">password</span><span class="token punctuation">:</span> <span class="token number">123456</span>
    <span class="token key atrule">dbcp2</span><span class="token punctuation">:</span>
      <span class="token key atrule">min-idle</span><span class="token punctuation">:</span> <span class="token number">5</span>         <span class="token comment">#最小连接数</span>
      <span class="token key atrule">initial-size</span><span class="token punctuation">:</span> <span class="token number">5</span>    <span class="token comment">#初始化连接数</span>
      <span class="token key atrule">max-total</span><span class="token punctuation">:</span> <span class="token number">10</span>      <span class="token comment">#最大连接数</span>
      <span class="token key atrule">max-wait-millis</span><span class="token punctuation">:</span> <span class="token number">200</span>    <span class="token comment">#等待连接最长的超时时间</span>

</code></pre></div><h4 id="编写主启动类"><a href="#编写主启动类" class="header-anchor">#</a> 编写主启动类</h4> <ul><li>记得主启动类放在根包下,com.xxx.xxx</li></ul> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span></span>XXX<span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span></span><span class="token class-name">SpringApplication</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">SpringBootApplication</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Provider8001_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Provider8001_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="springcloud添加组件的基本套路"><a href="#springcloud添加组件的基本套路" class="header-anchor">#</a> SpringCloud添加组件的基本套路</h2> <ol><li>新增这个组件的maven坐标GAV</li> <li>在启动类上面标注启动该组件（一般来说是@EnableXXXXX）</li> <li>编写业务逻辑代码</li></ol> <h2 id="eureka服务注册与发现"><a href="#eureka服务注册与发现" class="header-anchor">#</a> Eureka服务注册与发现</h2> <h3 id="eureka介绍及原理"><a href="#eureka介绍及原理" class="header-anchor">#</a> Eureka介绍及原理</h3> <h4 id="理解"><a href="#理解" class="header-anchor">#</a> 理解</h4> <p>==Eureka就像一个物业管理公司，其他微服务就像小区的住户，每个住户入住时都要向物业管理公司注册，并定时向物业公司交管理费==</p> <h4 id="介绍-2"><a href="#介绍-2" class="header-anchor">#</a> 介绍</h4> <ul><li>Eureka是一个基于REST的服务，用于定位服务，以实现云端中间层服务发现和故障转移。</li> <li>Eureka主管服务注册与发现，在微服务中，以后了这两者，只需要使用服务的标识符（==就是那个在每个服务的yml文件中取得服务名称==），就可以访问到服务，不需要修改服务调用的配置文件</li> <li>Eureka遵循AP原则（高可用，分区容错性），因为使用了自我保护机制所以保证了高可用</li></ul> <h4 id="原理"><a href="#原理" class="header-anchor">#</a> 原理</h4> <ul><li>Eureka使用的是C-S结构（客户端-服务端）</li> <li>两大组件：Eureka Server（提供注册服务）、 Eureka Client（JAVA客户端，负责发送心跳）</li> <li>系统中的其他微服务使用Eureka客户端连接到Eureka服务端维持心跳连接（即注册）。SpringCloud的其他模块可以通过Eureka Server 来发现系统中的微服务并加以调用</li></ul> <p><img src="https://imgkr.cn-bj.ufileos.com/691ac770-0a14-4590-8afa-cf9aeb398384.png" alt="Eureka的架构图"></p> <h3 id="eureka服务注册中心构建"><a href="#eureka服务注册中心构建" class="header-anchor">#</a> Eureka服务注册中心构建</h3> <h4 id="加入服务端依赖"><a href="#加入服务端依赖" class="header-anchor">#</a> 加入服务端依赖</h4> <div class="language-xml extra-class"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-eureka-server<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h4 id="配置yml"><a href="#配置yml" class="header-anchor">#</a> 配置yml</h4> <ul><li>==理解：物业公司肯定不向自己注册自己，并肯定知道自己在哪，不用参加检索==</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">7001</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> localhost
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">register-with-eureka</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>     <span class="token comment">#false表示不向注册中心注册自己</span>
    <span class="token key atrule">fetch-registry</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>           <span class="token comment">#false表示自己就是注册中心，职责是维护实例，不参加检索</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//$<span class="token punctuation">{</span>eureka.instance.hostname<span class="token punctuation">}</span><span class="token punctuation">:</span>$<span class="token punctuation">{</span>server.port<span class="token punctuation">}</span>/eureka/    <span class="token comment">#设置eureka server的交互地址，即对外暴露的地址</span>
</code></pre></div><h4 id="添加启动类"><a href="#添加启动类" class="header-anchor">#</a> 添加启动类</h4> <ul><li>==注意：要在类前加@EnableEurekaServer标注==</li></ul> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span></span>XXX<span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span></span><span class="token class-name">SpringApplication</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">SpringBootApplication</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>cloud<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>eureka<span class="token punctuation">.</span>server<span class="token punctuation">.</span></span><span class="token class-name">EnableEurekaServer</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaServer</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Eureka7001_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Eureka7001_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="验证是否构建成功"><a href="#验证是否构建成功" class="header-anchor">#</a> 验证是否构建成功</h4> <p>启动主程序，访问该服务地址即可</p> <h3 id="向eureka注册中心注册微服务"><a href="#向eureka注册中心注册微服务" class="header-anchor">#</a> 向Eureka注册中心注册微服务</h3> <h4 id="增加依赖"><a href="#增加依赖" class="header-anchor">#</a> 增加依赖</h4> <p>在要注册的微服务的pom.xml文件中增加依赖</p> <div class="language-xml extra-class"><pre class="language-xml"><code>		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-eureka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>	
</code></pre></div><h4 id="修改yml"><a href="#修改yml" class="header-anchor">#</a> 修改yml</h4> <ul><li>在application.yml中增加以内容，将客户端注册到服务列表内</li> <li>==理解：小区用户要找到物业管理处的地址进行注册==</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//localhost<span class="token punctuation">:</span>7001/eureka
</code></pre></div><h4 id="主启动类增加注解"><a href="#主启动类增加注解" class="header-anchor">#</a> 主启动类增加注解</h4> <ul><li>增加@EnableEurekaClient注解</li></ul> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaClient</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Provider8001_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Provider8001_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="actuator与微服务注册完善"><a href="#actuator与微服务注册完善" class="header-anchor">#</a> actuator与微服务注册完善</h3> <h4 id="主机名称与服务名称的修改"><a href="#主机名称与服务名称的修改" class="header-anchor">#</a> 主机名称与服务名称的修改</h4> <ul><li>修改服务名称，在yml中eureka节点下添加如下内容</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code> <span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">instance-id</span><span class="token punctuation">:</span> dept8001		<span class="token comment">#修改别名</span>
    <span class="token key atrule">prefer-ip-address</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>		<span class="token comment">#显示IP地址</span>
</code></pre></div><h4 id="info内容的详细信息修改"><a href="#info内容的详细信息修改" class="header-anchor">#</a> info内容的详细信息修改</h4> <h5 id="作用"><a href="#作用" class="header-anchor">#</a> 作用</h5> <p>在查看Eureka时点击进入某个微服务的info时，能给查看者一些必要的信息，可以帮助查看者快速的了解该微服务，开发中十分有意义。</p> <h5 id="修改方法"><a href="#修改方法" class="header-anchor">#</a> 修改方法</h5> <ol><li>==当前工程==添加依赖</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-actuator<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>==总的父工程==的build节点下添加如下内容</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>finalName</span><span class="token punctuation">&gt;</span></span>microservicecloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>finalName</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>resources</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>resource</span><span class="token punctuation">&gt;</span></span>
             	<span class="token comment">&lt;!--允许扫描该路径下的资源文件--&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>directory</span><span class="token punctuation">&gt;</span></span>src/main/resources<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>directory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filtering</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filtering</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>resource</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>resources</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugins</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.maven.plugins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>maven-resources-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>delimiters</span><span class="token punctuation">&gt;</span></span>
                     	<span class="token comment">&lt;!--指定动态获取以$标志开头结尾的信息--&gt;</span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>delimit</span><span class="token punctuation">&gt;</span></span>$<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>delimit</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>delimiters</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugins</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="3"><li>在==当前工程== 的application.yml文件添加回显信息</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">info</span><span class="token punctuation">:</span>
  <span class="token key atrule">author</span><span class="token punctuation">:</span> XXX
  <span class="token key atrule">build-version</span><span class="token punctuation">:</span> $project.version$
</code></pre></div><h3 id="eureka的自我保护"><a href="#eureka的自我保护" class="header-anchor">#</a> Eureka的自我保护</h3> <h4 id="介绍-3"><a href="#介绍-3" class="header-anchor">#</a> 介绍</h4> <p>Eureka的自我保护机制主要是为了网络异常时保持高可用设计的，当在Eureka中注册的微服务超过设定是时间内（默认90秒）没有向Eureka服务端发送心跳，该微服务会进入自我保护模式。在自我保护模式中，Eureka会保护服务注册表中的信息，不会注销任何服务实例，直至收到的心跳数恢复至阈值以上，该微服务退出自我保护模式。</p> <h4 id="理解-2"><a href="#理解-2" class="header-anchor">#</a> 理解</h4> <p>好死不如赖活：Eureka的设计哲学是宁可保留错误的服务信息，也不盲目注销可能健康的服务。所以异常的服务不会被注销，而是进入了自我保护模式。</p> <h4 id="自我保护模式的开关"><a href="#自我保护模式的开关" class="header-anchor">#</a> 自我保护模式的开关</h4> <p>在Eureka Server模块下的yml文件中添加配置信息即可，true表示打开自我保护模式；false表示关闭自我保护模式（不推荐）</p> <div class="language-java extra-class"><pre class="language-java"><code>  server<span class="token operator">:</span>
    enable<span class="token operator">-</span>self<span class="token operator">-</span>preservation<span class="token operator">:</span> <span class="token boolean">false</span>
</code></pre></div><h3 id="eureka的服务发现"><a href="#eureka的服务发现" class="header-anchor">#</a> Eureka的服务发现</h3> <h4 id="介绍-4"><a href="#介绍-4" class="header-anchor">#</a> 介绍</h4> <p>系统中的微服务可以通过Eureka的服务发现去获得在Eureka中注册的服务的信息，这是一个对外暴露的接口。</p> <h4 id="使用方法-provider中"><a href="#使用方法-provider中" class="header-anchor">#</a> 使用方法（provider中）</h4> <ol><li>注入DiscoveryClient 对象（spring包下的），在controller方法中获取</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@Autowired</span>
<span class="token keyword">private</span> <span class="token class-name">DiscoveryClient</span> discoveryClient<span class="token punctuation">;</span>    

<span class="token annotation punctuation">@ResponseBody</span>
<span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/provider/discovery&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">discovery</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> list <span class="token operator">=</span> discoveryClient<span class="token punctuation">.</span><span class="token function">getServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ServiceInstance</span><span class="token punctuation">&gt;</span></span> insList <span class="token operator">=</span> discoveryClient<span class="token punctuation">.</span><span class="token function">getInstances</span><span class="token punctuation">(</span><span class="token string">&quot;MICROSERVICECLOUD-DEPT&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">ServiceInstance</span> si<span class="token operator">:</span>insList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>si<span class="token punctuation">.</span><span class="token function">getHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;,&quot;</span> <span class="token operator">+</span> si<span class="token punctuation">.</span><span class="token function">getServiceId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;,&quot;</span> <span class="token operator">+</span>si<span class="token punctuation">.</span><span class="token function">getPort</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;,&quot;</span> <span class="token operator">+</span>si<span class="token punctuation">.</span><span class="token function">getUri</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;,&quot;</span> <span class="token operator">+</span>si<span class="token punctuation">.</span><span class="token function">getMetadata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>discoveryClient<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>在主启动类中加入@EnableDiscoveryClient注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaClient</span>
<span class="token annotation punctuation">@EnableDiscoveryClient</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Provider8001_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Provider8001_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="使用方法-consumer中"><a href="#使用方法-consumer中" class="header-anchor">#</a> 使用方法（consumer中）</h4> <p>在controller方法中使用restTemplate对象调用provider中暴露的URL 并获得返回对象即可</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/discovery&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">discovery</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> restTemplate<span class="token punctuation">.</span><span class="token function">getForObject</span><span class="token punctuation">(</span>URL_PREFIX<span class="token operator">+</span><span class="token string">&quot;/provider/discovery&quot;</span><span class="token punctuation">,</span><span class="token class-name">Object</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><h3 id="eureka的集群配置"><a href="#eureka的集群配置" class="header-anchor">#</a> Eureka的集群配置</h3> <h4 id="集群"><a href="#集群" class="header-anchor">#</a> 集群</h4> <p>集群就是在不同的机器上配置相同的服务来构建要一个大的运算整体</p> <h4 id="实现集群"><a href="#实现集群" class="header-anchor">#</a> 实现集群</h4> <ol><li>新建N个Eureka Server模块</li> <li>每个模块的pom.xml中加入与单个Eureka Server相同的依赖</li> <li>每个模块加入主程序（记得加@EnableEurekaServer注解）</li> <li>修改hosts文件（Win7的路径是C:\Windows\System32\drivers\etc）</li></ol> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token number">127.0</span>.0.1 eureka7001.com
<span class="token number">127.0</span>.0.1 eureka7002.com
<span class="token number">127.0</span>.0.1 eureka7003.com
</code></pre></div><ol start="5"><li>修改Eureka Server模块的application.yml文件，加入集群，主要修改两个地方：</li></ol> <ul><li>hostname：修改为hosts文件中映射的地址</li> <li>service-url下的defaultZone节点：填入集群中另外的server服务端的地址</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">7001</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> eureka7001.com    <span class="token comment">#hostname为hosts文件中映射的地址</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">register-with-eureka</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>     <span class="token comment">#false表示不向注册中心注册自己</span>
    <span class="token key atrule">fetch-registry</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>           <span class="token comment">#false表示自己就是注册中心，职责是维护实例，不参加检索</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token comment">#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/    #设置eureka server的交互地址</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7002.com<span class="token punctuation">:</span>7002/eureka/<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7003.com<span class="token punctuation">:</span>7003/eureka/  <span class="token comment">#其他两个服务端的地址</span>
</code></pre></div><ol start="6"><li>修改Eureka Client模块的application.yml文件，使其向集群注册服务</li></ol> <ul><li>service-url下的defaultZone节点：填入集群中需要向其注册server服务端的地址</li></ul> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7002.com<span class="token punctuation">:</span>7002/eureka<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7003.com<span class="token punctuation">:</span>7003/eureka
</code></pre></div><ol start="7"><li>访问地址</li></ol> <div class="language-shell extra-class"><pre class="language-shell"><code>http://eureka7001.com:7001
http://eureka7002.com:7002
http://eureka7003.com:7003
</code></pre></div><ol start="8"><li>==注：defaultZone中eureka/后缀是必须的，如果删除，Server类不会报错，但是Client注册时会报404错误==</li></ol> <h3 id="eureka与zookeeper对比"><a href="#eureka与zookeeper对比" class="header-anchor">#</a> Eureka与Zookeeper对比</h3> <h4 id="cap设计原则不同"><a href="#cap设计原则不同" class="header-anchor">#</a> CAP设计原则不同</h4> <p>Eureka遵守AP，Zookeeper遵守CP（C：强一致性，A：高可用，P：分区容错性，三者只能选其二，高并发下P必选）</p> <h4 id="网络波动下两者的处理对比"><a href="#网络波动下两者的处理对比" class="header-anchor">#</a> 网络波动下两者的处理对比</h4> <table><thead><tr><th style="text-align:left;">Zookeeper</th> <th>Eureka</th></tr></thead> <tbody><tr><td style="text-align:left;">当网络出现故障时，剩余zk集群会发起投票选举新的leader，但是此过程会持续30~120s，此过程对于高并发来说十分漫长，会导致整个注册服务的瘫痪，这是不可容忍的</td> <td>在15分钟内85%的节点都没有心跳，则注册中心 会认为客户端与之出现了网络故障，则会进入自动保护模式。1.Eureka不会移除没有收到心跳的服务；2.新的服务仍能在服务端注册，但是暂时不会被同步到其他节点上直到网络稳定</td></tr></tbody></table> <h4 id="结论"><a href="#结论" class="header-anchor">#</a> 结论</h4> <p>Eureka可以很好的应对网络故障导致部分节点失去连接的情况，而不会像zookeeper那样导致整个注册服务系统的瘫痪。</p> <h2 id="ribbon负载均衡"><a href="#ribbon负载均衡" class="header-anchor">#</a> Ribbon负载均衡</h2> <p>Spring Cloud Ribbon是基于Netflix Ribbon实现的一套==客户端==负载均衡工具。Ribbon会自动帮助你基于某种规则（简单轮询、随机连接等），也可以实现自定义的负载均衡算法。</p> <h3 id="负载均衡"><a href="#负载均衡" class="header-anchor">#</a> 负载均衡</h3> <ul><li><p>英文名称：Load Balance，微服务或分布式集群中常用的一种应用</p></li> <li><p>简单来说负载均衡就是将用户的请求ping平摊的分配到多个任务上，从而是系统达到HA（高可用）</p></li> <li><p>两种负载均衡：</p> <ol><li>集中式LB：偏硬件，服务的消费方和提供方之间使用独立的LB设施，由该设施负责把访问请求以某种策略转发至服务的提供方。</li> <li>进程内LB：骗软件， 将LB逻辑集成到消费方，消费方从服务注册中心指导哪些地址可用，再自己选择一个合适的服务器。</li></ol></li></ul> <h4 id="ribbon初步配置"><a href="#ribbon初步配置" class="header-anchor">#</a> Ribbon初步配置</h4> <ul><li>==Ribbon是客户端负载均衡工具！！！Ribbon是客户端负载均衡工具！！！Ribbon是客户端负载均衡工具！！！==所以应该配置在客户端</li></ul> <ol><li>加入依赖，因为Riboon需要依赖Eureka运行，所以要同时加入Eureka依赖</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-eureka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-ribbon<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>对实现类加入@LoadBalanced注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span>
<span class="token annotation punctuation">@LoadBalanced</span>
<span class="token keyword">public</span> <span class="token class-name">RestTemplate</span> <span class="token function">getRestTemplate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span>  <span class="token keyword">new</span> <span class="token class-name">RestTemplate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="3"><li>在application.yml文件中配置向注册中心注册，如果是作为消费者模块不提供服务，不应该注册自己</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7002.com<span class="token punctuation">:</span>7002/eureka/<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7003.com<span class="token punctuation">:</span>7003/eureka/
    <span class="token key atrule">register-with-eureka</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>				<span class="token comment">#作为消费者不提供服务，不应该注册自己</span>
</code></pre></div><ol start="4"><li>主启动类中加入@EnableEurekaClient注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaClient</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Consumer80_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Consumer80_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li>以上步骤1~4完成后即可在controller中直接通过服务名访问系统中的微服务，服务名作为URI</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> URL_PREFIX <span class="token operator">=</span> <span class="token string">&quot;http://MICROSERVICECLOUD-DEPT/&quot;</span><span class="token punctuation">;</span>
</code></pre></div><h4 id="ribbon负载均衡实现"><a href="#ribbon负载均衡实现" class="header-anchor">#</a> Ribbon负载均衡实现</h4> <p>架构示意图：</p> <p><img src="https://imgkr.cn-bj.ufileos.com/2eff6fc7-cf7d-450c-a61e-ea1d09708971.png" alt="Ribbon负载均衡架构"></p> <h5 id="实现方法"><a href="#实现方法" class="header-anchor">#</a> 实现方法</h5> <p>目标：构建provider集群后consumer通过负载均衡轮询调用在Eureka中注册的服务</p> <ol><li>构建集群，新开两个provider模块，将原provider的==代码部分和pom.xml中依赖照搬==到新的provider中</li> <li>将原provider中application.yml文件照搬到新provider，并修改端口号，若新的provider使用自己的数据库，则修改数据库信息（其他配置也一样，如修改别名）</li> <li>集群中服务名称必须一致！！！</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>dept   <span class="token comment">#同一集群下必须使用同一服务名！！！！！</span>
</code></pre></div><ol start="4"><li>启动服务，进行测试</li></ol> <h5 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h5> <p>Ribbon其实就是一个软负载均衡的客户端组件，可以和其他需要请求的客户端结合使用。</p> <h3 id="ribbon核心组件irule"><a href="#ribbon核心组件irule" class="header-anchor">#</a> Ribbon核心组件IRule</h3> <p>IRule：根据特定算法从服务列表中选取一个需要访问的服务</p> <h4 id="七大方法"><a href="#七大方法" class="header-anchor">#</a> 七大方法</h4> <p>==IRule是一个接口，七大方法是其自带的落地实现类==</p> <ul><li>RoundRobinRule：轮询（默认方法）</li> <li>RandomRule：随机</li> <li>AvailabilityFilteringRule：先过滤掉由于多次访问故障而处于断路器跳闸状态的服务，还有并发的连接数量超过阈值的服务，然后对剩余的服务进行轮询</li> <li>WeightedResponseTimeRule：根据平均响应时间计算服务的权重。统计信息不足时会按照轮询，统计信息足够会按照响应的时间选择服务</li> <li>RetryRule：正常时按照轮询选择服务，若过程中有服务出现故障，在轮询一定次数后依然故障，则会跳过故障的服务继续轮询。</li> <li>BestAvailableRule：先过滤掉由于多次访问故障而处于断路器跳闸状态的服务，然后选择一个并发量最小的服务</li> <li>ZoneAvoidanceRule：默认规则，符合判断server所在的区域的性能和server的可用性选择服务</li></ul> <h4 id="切换规则方法"><a href="#切换规则方法" class="header-anchor">#</a> 切换规则方法</h4> <p>只需在==配置类==中配置一个返回具体方法的bean即可</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> <span class="token class-name">IRule</span> <span class="token class-name">MyRule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">RandomRule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    
    <span class="token punctuation">}</span>
</code></pre></div><h3 id="自定义ribbon负载均衡算法"><a href="#自定义ribbon负载均衡算法" class="header-anchor">#</a> 自定义Ribbon负载均衡算法</h3> <h4 id="配置及包位置"><a href="#配置及包位置" class="header-anchor">#</a> 配置及包位置</h4> <ol><li>自定义的Ribbon算法类不能放在主启动类所在的包及子报下（确切来说是不能放在@ComponentScan注解的包及子包下），否则会被全局应用到Ribbon服务中。应该把自定义算法类放在另外新建的包下，且这个类应该是为==配置类==。（其实与普通切换负载均衡规则类似，只不过是位置不同而已，普通的可以放在主启动类所在的包，自定义的要放在外面的包下）</li> <li>主启动类添加@RibbonClient(name = &quot;微服务名&quot;,configuration = XXX.class)注解指定需要用到负载均衡的微服务名及自定义算法的class对象。</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaClient</span>
<span class="token annotation punctuation">@RibbonClient</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;MICROSERVICECLOUD-DEPT&quot;</span><span class="token punctuation">,</span>configuration <span class="token operator">=</span> <span class="token class-name">MyRule</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Consumer80_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Consumer80_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>####通过修改源代码获得自定义算法</p> <p>目标：每个服务调用5次后再进行轮询（调用次数不是很对，懒得改了)</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span></span><span class="token class-name">Rules</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>client<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">IClientConfig</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>loadbalancer<span class="token punctuation">.</span></span><span class="token class-name">AbstractLoadBalancerRule</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>loadbalancer<span class="token punctuation">.</span></span><span class="token class-name">ILoadBalancer</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>loadbalancer<span class="token punctuation">.</span></span><span class="token class-name">RoundRobinRule</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>netflix<span class="token punctuation">.</span>loadbalancer<span class="token punctuation">.</span></span><span class="token class-name">Server</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Logger</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">LoggerFactory</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Configuration</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">List</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span>atomic<span class="token punctuation">.</span></span><span class="token class-name">AtomicInteger</span><span class="token punctuation">;</span>


<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyRule</span> <span class="token keyword">extends</span> <span class="token class-name">AbstractLoadBalancerRule</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">AtomicInteger</span> nextServerCyclicCounter<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">boolean</span> AVAILABLE_ONLY_SERVERS <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">boolean</span> ALL_SERVERS <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> total <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> currentIndex <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">RoundRobinRule</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token class-name">MyRule</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        nextServerCyclicCounter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicInteger</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token class-name">MyRule</span><span class="token punctuation">(</span><span class="token class-name">ILoadBalancer</span> lb<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">setLoadBalancer</span><span class="token punctuation">(</span>lb<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token class-name">Server</span> <span class="token function">choose</span><span class="token punctuation">(</span><span class="token class-name">ILoadBalancer</span> lb<span class="token punctuation">,</span> <span class="token class-name">Object</span> key<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>lb <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">&quot;no load balancer&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token class-name">Server</span> server <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token keyword">int</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>server <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> count<span class="token operator">++</span> <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Server</span><span class="token punctuation">&gt;</span></span> reachableServers <span class="token operator">=</span> lb<span class="token punctuation">.</span><span class="token function">getReachableServers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Server</span><span class="token punctuation">&gt;</span></span> allServers <span class="token operator">=</span> lb<span class="token punctuation">.</span><span class="token function">getAllServers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> upCount <span class="token operator">=</span> reachableServers<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> serverCount <span class="token operator">=</span> allServers<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>upCount <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">(</span>serverCount <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">&quot;No up servers available from load balancer: &quot;</span> <span class="token operator">+</span> lb<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>total <span class="token operator">&gt;</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                total <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
                <span class="token keyword">int</span> nextServerIndex <span class="token operator">=</span> <span class="token function">incrementAndGetModulo</span><span class="token punctuation">(</span>serverCount<span class="token punctuation">)</span><span class="token punctuation">;</span>
                currentIndex <span class="token operator">=</span> nextServerIndex<span class="token punctuation">;</span>
                server <span class="token operator">=</span> allServers<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>nextServerIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>currentIndex<span class="token operator">&gt;=</span>serverCount<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    currentIndex <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
                server <span class="token operator">=</span> allServers<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>currentIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
                total<span class="token operator">++</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>


            <span class="token keyword">if</span> <span class="token punctuation">(</span>server <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token comment">/* Transient. */</span>
                <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token keyword">yield</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">continue</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token keyword">if</span> <span class="token punctuation">(</span>server<span class="token punctuation">.</span><span class="token function">isAlive</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>server<span class="token punctuation">.</span><span class="token function">isReadyToServe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">return</span> <span class="token punctuation">(</span>server<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token comment">// Next.</span>
            server <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>count <span class="token operator">&gt;=</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">&quot;No available alive servers after 10 tries from load balancer: &quot;</span>
                    <span class="token operator">+</span> lb<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> server<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.
     *
     * @param modulo The modulo to bound the value of the counter.
     * @return The next value.
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> <span class="token function">incrementAndGetModulo</span><span class="token punctuation">(</span><span class="token keyword">int</span> modulo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">int</span> current <span class="token operator">=</span> nextServerCyclicCounter<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> next <span class="token operator">=</span> <span class="token punctuation">(</span>current <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">%</span> modulo<span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>nextServerCyclicCounter<span class="token punctuation">.</span><span class="token function">compareAndSet</span><span class="token punctuation">(</span>current<span class="token punctuation">,</span> next<span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">return</span> next<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token class-name">Server</span> <span class="token function">choose</span><span class="token punctuation">(</span><span class="token class-name">Object</span> key<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token function">choose</span><span class="token punctuation">(</span><span class="token function">getLoadBalancer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> key<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">initWithNiwsConfig</span><span class="token punctuation">(</span><span class="token class-name">IClientConfig</span> clientConfig<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><h2 id="feign负载均衡"><a href="#feign负载均衡" class="header-anchor">#</a> Feign负载均衡</h2> <p>Feign是一个声明式WebService客户端，使用方法时定义一个接口并在上面添加注解即可。Feign支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装，使其支持SpringMVC和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。</p> <h3 id="使用案例"><a href="#使用案例" class="header-anchor">#</a> 使用案例</h3> <ol><li>新建Feign模块，加入依赖（其实跟80消费者差不多，主要是多了Feign依赖）</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.XXX<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>microservice-api<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>${project.version}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-web<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-feign<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-eureka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-ribbon<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token comment">&lt;!--热部署--&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>springloaded<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-devtools<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>因为Feign开发其实是面向接口编程，所以Feign接口可以放在api模块中供各模块使用，所以要在api模块中添加Feign依赖</li> <li>在api中编写接口，接口上添加@FeignClient注解，并通过value指定作用的微服务名</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@FeignClient</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;MICROSERVICECLOUD-DEPT&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">DeptClientService</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">addDept</span><span class="token punctuation">(</span><span class="token class-name">Dept</span> dept<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Dept</span><span class="token punctuation">&gt;</span></span> <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept/{id}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="4"><li>在Feign模块中编写Controller，并注入FeignClient接口，直接调用service接口中的方法即可（因为声明Feign接口时已经指定过微服务，所以访问时会正确地找到微服务）</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/consumer&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConsumerDeptController</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">DeptClientService</span> service<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">addDept</span><span class="token punctuation">(</span><span class="token class-name">Dept</span> dept<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> service<span class="token punctuation">.</span><span class="token function">addDept</span><span class="token punctuation">(</span>dept<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Dept</span><span class="token punctuation">&gt;</span></span> <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> service<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept/{id}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> service<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li>修改Feign模块的主启动类，加入@EnableFeignClients注解和@ComponentScan注解（主要是扫描api中声明的接口）</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableEurekaClient</span>
<span class="token annotation punctuation">@EnableFeignClients</span><span class="token punctuation">(</span>basePackages <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">&quot;com.XXX&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@ComponentScan</span><span class="token punctuation">(</span><span class="token string">&quot;com.XXX&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Consumer80Feign_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Consumer80Feign_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="6"><li>启动后访问，即会按照轮询的方式调用provider集群</li></ol> <h3 id="总结-2"><a href="#总结-2" class="header-anchor">#</a> 总结</h3> <ul><li>Feign通过接口方法调用REST服务，在Eureka中查找对应的服务</li> <li>Feign集成了Ribbon技术，所以也支持负载均衡（轮询）</li></ul> <h2 id="hystrix断路器"><a href="#hystrix断路器" class="header-anchor">#</a> Hystrix断路器</h2> <h3 id="分布式系统面临的问题"><a href="#分布式系统面临的问题" class="header-anchor">#</a> 分布式系统面临的问题</h3> <h4 id="扇出"><a href="#扇出" class="header-anchor">#</a> 扇出</h4> <p>多个微服务互相调用的时候，如果A调用B、C，而B、C又继续调用其他微服务，这就是扇出（像一把扇子一样慢慢打开。</p> <h4 id="服务雪崩"><a href="#服务雪崩" class="header-anchor">#</a> 服务雪崩</h4> <ul><li>删除过程中，如果某一个环节的服务出现故障或连接超时，就会导致前面的服务占用越来越多的资源，进而引起系统崩溃，就是“雪崩效应”。</li> <li>对于高流量的应用来说，单一的后端依赖会导致服务器所有的资源都在几秒钟内饱和。比失败更糟糕的是，这些应用程序还可能导致服务之间的延迟增加，备份队列，线程和其他系统资源紧张，导致整个系统发生更多的级联故障。这些都表示需要==对故障和延迟进行隔离和管理==，以便单个依赖关系的失败，不能取消整个应用程序或系统。</li></ul> <h3 id="hystrix介绍"><a href="#hystrix介绍" class="header-anchor">#</a> Hystrix介绍</h3> <ul><li>Hystrix是一个用于处理分布式系统延迟和容错的开源库。分布式系统中，依赖避免不了调用失败，比如超时，异常等。Hystrix能保证在出现问题的时候，不会导致整体服务失败，避免级联故障，以提高分布式系统的弹性。</li> <li>Hystrix类似一个“断路器”，当系统中异常发生时，断路器给调用返回一个符合预期的，可处理的FallBack，这样就可以避免长时间无响应或抛出异常，使故障不能再系统中蔓延，造成雪崩。</li></ul> <h4 id="服务熔断"><a href="#服务熔断" class="header-anchor">#</a> 服务熔断</h4> <ul><li>熔断机制的注解是@HystrixCommand</li> <li>熔断机制是应对雪崩效应的一种==链路保护机制==，一般存在于服务端</li> <li>当扇出链路的某个服务出现故障或响应超时，会进行==服务降级==，进而==熔断该节点的服务调用==，快速返回“错误”的相应信息。、</li> <li>Hystrix的熔断存在阈值，缺省是5秒内20次调用失败就会触发</li></ul> <h5 id="熔断案例"><a href="#熔断案例" class="header-anchor">#</a> 熔断案例</h5> <ol><li>构建一个新的provider module（如复制8001module）</li> <li>pom.xml加入hystrix依赖（一定要配合Eureka）</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-hystrix<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="3"><li>application.xml中配置端口和Eureka信息（必配）和其他框架的配置信息（可选，如mybatis）</li> <li>编写具体业务逻辑</li> <li>controller类中，在需要配置Fallback的方法上加入@@HystrixCommand(fallbackMethod = &quot;XXX&quot;)注解，XXX为FallBack方法名本例中作为测试所以抛出了异常</li></ol> <div class="language-java extra-class"><pre class="language-java"><code>    <span class="token annotation punctuation">@ResponseBody</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept/{id}&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@HystrixCommand</span><span class="token punctuation">(</span>fallbackMethod <span class="token operator">=</span> <span class="token string">&quot;nullDeptFallBack&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Dept</span> dept <span class="token operator">=</span> deptService<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">==</span> dept<span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">&quot;返回值为空！&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> dept<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><ol start="6"><li>根据需要配置FallBack的方法返回值编写代码</li></ol> <div class="language-java extra-class"><pre class="language-java"><code> <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">nullDeptFallBack</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token number">111</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Dept</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setId</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setDeptName</span><span class="token punctuation">(</span><span class="token string">&quot;nullName&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setDbSource</span><span class="token punctuation">(</span><span class="token string">&quot;nullDB&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><ol start="7"><li>主启动类中加入@EnableCircuitBreaker注解</li> <li>开启服务，测试</li></ol> <h4 id="解耦与降级处理"><a href="#解耦与降级处理" class="header-anchor">#</a> 解耦与降级处理</h4> <h5 id="降级"><a href="#降级" class="header-anchor">#</a> 降级</h5> <ul><li>当系统整体资源快不够的时候，忍痛将部分服务暂时关闭，带渡过难关后，再重新开启。</li> <li>降级处理时在==客户端==完成的，与服务端没有关系</li> <li>理解：所谓降级，一般是从==整体负荷==考虑，当某个服务熔断之后，服务器将不再被调用，此时客户端可以自己准备一个本地的FallBack回调，返回一个缺省值。这样做虽然服务水平下降，但好歹可用，比直接挂掉好。</li></ul> <h5 id="为什么要解耦"><a href="#为什么要解耦" class="header-anchor">#</a> 为什么要解耦</h5> <p>如果按照上面的熔断案例来做的话，Controller下的每个方法，都要给其编写一个FallBack方法，当方法慢慢变多，就会造成代码膨胀，一个是增加编写的工作量，另外一个也会增大维护的难度，代码的耦合度也会高，是十分不合理的，所以要将其解耦。</p> <h5 id="解耦思路"><a href="#解耦思路" class="header-anchor">#</a> 解耦思路</h5> <p>因为服务端的是通过实现接口访问服务端的，如果在父接口上实现了FallBack方法，通过这样一种方式去维护起来就能实现解耦，也顺便完成了降级的机制。</p> <h5 id="解耦-降级案例"><a href="#解耦-降级案例" class="header-anchor">#</a> 解耦&amp;降级案例</h5> <ol><li>在api模块中新建实现了FallbackFactory<T>接口的类，其中泛型T就是我们需要维护其FallBack的接口方法，并实现其create方法，在create方法中返回实现了T的对象，使用匿名内部类实现T。==注意：这个类一定要加@Component注解！！这个类一定要加@Component注解！！这个类一定要加@Component注解！！==</T></li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span></span>XXX<span class="token punctuation">.</span>entity<span class="token punctuation">.</span><span class="token class-name">Dept</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">feign<span class="token punctuation">.</span>hystrix<span class="token punctuation">.</span></span><span class="token class-name">FallbackFactory</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>stereotype<span class="token punctuation">.</span></span><span class="token class-name">Component</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">List</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeptClientServiceFallBackFactory</span> <span class="token keyword">implements</span> <span class="token class-name">FallbackFactory</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">DeptClientService</span><span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">DeptClientService</span> <span class="token function">create</span><span class="token punctuation">(</span><span class="token class-name">Throwable</span> throwable<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DeptClientService</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">addDept</span><span class="token punctuation">(</span><span class="token class-name">Dept</span> dept<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Dept</span><span class="token punctuation">&gt;</span></span> <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Dept</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setId</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setDeptName</span><span class="token punctuation">(</span><span class="token string">&quot;服务器跪了,&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setDbSource</span><span class="token punctuation">(</span><span class="token string">&quot;迟点来吧&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>修改步骤1中传入的泛型T接口，添加@FeignClient(fallbackFactory = T.class)注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@FeignClient</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;MICROSERVICECLOUD-DEPT&quot;</span><span class="token punctuation">,</span>fallbackFactory <span class="token operator">=</span> <span class="token class-name">DeptClientServiceFallBackFactory</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">DeptClientService</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">addDept</span><span class="token punctuation">(</span><span class="token class-name">Dept</span> dept<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Dept</span><span class="token punctuation">&gt;</span></span> <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/dept/{id}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Dept</span> <span class="token function">findById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token class-name">Integer</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="3"><li>修改consumer feign模块的application.xml文件，开启hystrix（注：在IDEA中可能没有代码提示，开启的true也没有正常高亮，但好像不需要做额外操作也不影响结果）</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">feign</span><span class="token punctuation">:</span>
  <span class="token key atrule">hystrix</span><span class="token punctuation">:</span>
    <span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
</code></pre></div><ol start="4"><li>开启服务并测试</li></ol> <h4 id="hystrixdashboard服务监控"><a href="#hystrixdashboard服务监控" class="header-anchor">#</a> HystrixDashboard服务监控</h4> <p>介绍：SpringCloud对Hystrix Dashboard进行了整合，可以对通过Hystrix发起的请求进行准实时统计，并以报表和图形的形式展示给用户（包括每秒执行多少次请求成功和失败等）。</p> <h5 id="配置案例"><a href="#配置案例" class="header-anchor">#</a> 配置案例</h5> <ol><li>新建HystrixDashboard模块，pom.xml文件加入HystrixDashboard依赖，其他依赖包括Feign，Ribbon，Eureka（可参考80模块的依赖）</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-hystrix-dashboard<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>application.yml文件中配置端口（如9001）</li> <li>provider类中确认要加入actuator依赖（此为监控依赖）</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-boot-starter-actuator<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="4"><li>编写主启动类，上标@EnableHystrixDashboard标注</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableHystrixDashboard</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DashBoard9001_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">DashBoard9001_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li>启动服务进行测试，访问地址：http://localhost:9001/hystrix，（根据配置端口号），==看到刺猬表示已经配置好了==</li></ol> <h5 id="如何监控"><a href="#如何监控" class="header-anchor">#</a> 如何监控</h5> <ul><li>在dashboard界面中，填入需要监控的服务地址和端口号加上\hystrix.stream和监测间隔即可进入监控。（如http://localhost:8001/hystrix.stream</li></ul> <h5 id="监控分析"><a href="#监控分析" class="header-anchor">#</a> 监控分析</h5> <ul><li>七色：进入监控界面后会有其中颜色的数字，其含义可以对应右上角相同颜色的单词表示的状态，其值代表该状态下触发的次数</li> <li>一圈：圈的大小代表该服务的流量，圈越大流量越大</li> <li>一线：代表监控间隔中，服务被访问的频率的折线图</li> <li>通过观察这些就可以在大量的实例中找出故障实例和高压实例进行修复和维护。</li></ul> <p><img src="https://imgkr.cn-bj.ufileos.com/fda47b35-6e45-4043-9880-aecd18aed5c5.png" alt="Dashboard监控说明图"></p> <h2 id="zuul路由网关"><a href="#zuul路由网关" class="header-anchor">#</a> Zuul路由网关</h2> <h3 id="概述"><a href="#概述" class="header-anchor">#</a> 概述</h3> <ol><li><p>代理：Zuul提供外部的请求转发到具体的微服务实例中的服务</p></li> <li><p>路由：Zuul可以对外部访问实现统一的入口</p></li> <li><p>过滤：Zuul可以对外部访问进行干预，如请求校验、服务聚合等</p></li> <li><p>Zuul需要配合Eureka使用，需要在Eureka中注册并获得其他微服务的信息</p></li> <li><p>理解：Zuul就像大楼的保安，可以请他找人（代理），找的人在外面叫什么名字（路由），准不准你进楼（过滤）。因为保安属于物业公司，所以保安要在物业公司注册，所获得的信息也来源于物业公司（与Eureka的关系）。</p></li></ol> <h3 id="基本配置"><a href="#基本配置" class="header-anchor">#</a> 基本配置</h3> <ol><li>构建新的Zuul模块并在pom.xml中加入依赖（Zuul和Eureka必须同时加入）</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-eureka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-zuul<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>新建application.yml文件并配置（一定要向Eureka注册，因为Zuul本身也是一个微服务）</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">9527</span>

<span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>zuul   <span class="token comment">#为这个服务取名，非常重要！！！！！</span>

<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7002.com<span class="token punctuation">:</span>7002/eureka/<span class="token punctuation">,</span>http<span class="token punctuation">:</span>//eureka7003.com<span class="token punctuation">:</span>7003/eureka/
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">instance-id</span><span class="token punctuation">:</span> zuul.com
    <span class="token key atrule">prefer-ip-address</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
</code></pre></div><ol start="3"><li>修改hosts文件（非必须，不过能更好看出效果）</li></ol> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token number">127.0</span>.0.0 zuul.com
</code></pre></div><ol start="4"><li>创建主启动类，并加入@EnableZuulProxy注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableZuulProxy</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Zuul9527_APP</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">Zuul9527_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li><p>启动测试，访问规则：步骤3中指定映射+端口号+微服务名称+访问路径。</p> <p>例子：http://zuul.com:9527/microservicecloud-dept/dept</p></li></ol> <h3 id="路由访问映射规则"><a href="#路由访问映射规则" class="header-anchor">#</a> 路由访问映射规则</h3> <h4 id="服务名映射和统一公共前缀"><a href="#服务名映射和统一公共前缀" class="header-anchor">#</a> 服务名映射和统一公共前缀</h4> <p>当不向暴露真实的服务名时，可以对服务名进行映射，只需在application.yml中配置即可，==具体作用看注释==</p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">zuul</span><span class="token punctuation">:</span>
  <span class="token key atrule">routes</span><span class="token punctuation">:</span>
  	<span class="token comment">#dept0是可以自定义的只是作为区分，没什么具体意义</span>
    <span class="token key atrule">dept0.serviceId</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>dept		
    <span class="token comment">#路径也是自定义的，支持通配符</span>
    <span class="token key atrule">dept0.path</span><span class="token punctuation">:</span> /dept10/<span class="token important">**</span>						
  <span class="token comment">#需要隐藏的服务名，可以使用通配符，配置之后通过这个微服务名访问就失效了</span>
  <span class="token key atrule">ignored-services</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>*
  <span class="token comment">#设置统一公共前缀，设置后访问路径：http://zuul.com:9527/nihao/dept10/dept/3</span>
  <span class="token key atrule">prefix</span><span class="token punctuation">:</span> /nihao								
</code></pre></div><p>==注：因为Zuul是针对外部访问管理的，所以配置了隐藏的服务，在系统中其他模块进行服务名访问时依然可以正常运行的，这点可以通过打开consumer模块进行验证！==</p> <h2 id="springcloud-config-分布式配置中心"><a href="#springcloud-config-分布式配置中心" class="header-anchor">#</a> SpringCloud Config 分布式配置中心</h2> <p>分布式系统面临的配置问题：微服务意味着将单体应用拆分成一个个自服务，这些服务都是要相应的配置信息才能运行，随着系统内微服务数量越来越多，配置信息也不断地增多，所以一套集中式的、动态的配置管理设施是必不可少的。</p> <h3 id="概述-2"><a href="#概述-2" class="header-anchor">#</a> 概述</h3> <ul><li>SpringCloud Config是一个提供外部集中式配置管理的设施，配置服务器为各种不同的额微服务应用提供了一个中心化的外部配置</li> <li>SpringCloud Config分为客户端和服务端两部分
<ol><li>服务端：分布式配置中心，是一个独立的微服务，用来连接并为客户端提供配置信息，加密/解密信息等访问接口</li> <li>客户端：通过指定的配置中心获取配置资源，cloud推荐用git来存储配置信息</li></ol></li> <li>SpringCloud Config解决的问题：
<ol><li>集中管理配置文件</li> <li>不同环境不同配置，动态化的配置更新</li> <li>运行期间动态调整配置，不再需要在每个服务部署的机器上编写配置文件，让服务中心统一为服务拉取配置文件</li> <li>当配置发生变动时，服务不需要重启即可感知配置变化并应用</li> <li>将配置信息以REST接口形式暴露</li></ol></li></ul> <p><img src="https://imgkr.cn-bj.ufileos.com/58d099b0-7e49-4dfc-8fa7-bcf5be13987e.png" alt="SpringCloud Config架构图"></p> <h3 id="springcloud-config服务端与github通讯"><a href="#springcloud-config服务端与github通讯" class="header-anchor">#</a> SpringCloud Config服务端与Github通讯</h3> <p>目标：将配置文件部署在github，Config服务端从github获取配置</p> <h4 id="案例"><a href="#案例" class="header-anchor">#</a> 案例</h4> <ol><li>新建ConfigServer模块并配置pom.xml</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>		<span class="token comment">&lt;!-- springCloud Config --&gt;</span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-config-server<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
		<span class="token comment">&lt;!-- 避免Config的Git插件报错：org/eclipse/jgit/api/TransportConfigCallback --&gt;</span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.eclipse.jgit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>org.eclipse.jgit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>4.10.0.201712302008-r<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="2"><li>建立远程仓库，并上传配置文件。如下例</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span> 
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> 
        <span class="token key atrule">active</span><span class="token punctuation">:</span>
           <span class="token punctuation">-</span> dev
<span class="token punctuation">---</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> dev
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>config<span class="token punctuation">-</span>XXX<span class="token punctuation">-</span>dev
<span class="token punctuation">---</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> test
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>config<span class="token punctuation">-</span>XXX<span class="token punctuation">-</span>test
</code></pre></div><ol start="3"><li>在application.xml文件中配置github地址</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">3344</span>

<span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token comment">#为这个服务取名，非常重要！！！！！</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>config
  <span class="token key atrule">cloud</span><span class="token punctuation">:</span>
    <span class="token key atrule">config</span><span class="token punctuation">:</span>
      <span class="token key atrule">server</span><span class="token punctuation">:</span>
        <span class="token key atrule">git</span><span class="token punctuation">:</span>
          <span class="token comment"># uri填github上仓库地址</span>
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> https<span class="token punctuation">:</span>//github.com/XXXX/SpringCloud_Configuration.git
</code></pre></div><ol start="4"><li>编写主启动类，加入@EnableConfigServer注解</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token annotation punctuation">@EnableConfigServer</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConfigServer3344_APP</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">ConfigServer3344_APP</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li>启动服务并尝试访问配置文件，有以下五种访问配置规则
<ul><li>{application}：配置文件的文件名</li> <li>{profile}：读取的环境</li> <li>{lable}：分支</li></ul></li></ol> <div class="language-SHELL extra-class"><pre class="language-shell"><code>/<span class="token punctuation">{</span>application<span class="token punctuation">}</span>/<span class="token punctuation">{</span>profile<span class="token punctuation">}</span><span class="token punctuation">[</span>/<span class="token punctuation">{</span>lable<span class="token punctuation">}</span><span class="token punctuation">]</span>
/<span class="token punctuation">{</span>application<span class="token punctuation">}</span>-<span class="token punctuation">{</span>profile<span class="token punctuation">}</span>.yml
/<span class="token punctuation">{</span>lable<span class="token punctuation">}</span>/<span class="token punctuation">{</span>application<span class="token punctuation">}</span>-<span class="token punctuation">{</span>profile<span class="token punctuation">}</span>.yml
/<span class="token punctuation">{</span>application<span class="token punctuation">}</span>-<span class="token punctuation">{</span>profile<span class="token punctuation">}</span>.properties
/<span class="token punctuation">{</span>lable<span class="token punctuation">}</span>/<span class="token punctuation">{</span>application<span class="token punctuation">}</span>-<span class="token punctuation">{</span>profile<span class="token punctuation">}</span>.properties
</code></pre></div><p>可用例子（返回格式可能不大相同，但返回值相同）：</p> <ul><li>http://config3344.com:3344/application-test.yml</li> <li>http://config3344.com:3344/master/application-dev.yml</li> <li>http://config3344.com:3344/application-test.yml/master</li></ul> <p>不可用例子：</p> <ul><li>没有该环境，返回空值：http://config3344.com:3344/application-test11.yml/master</li> <li>没有配置文件，犯回错误页面：http://config3344.com:3344/lkjliiusdfsddsfl.yml</li></ul> <h3 id="bootstrap-yml介绍"><a href="#bootstrap-yml介绍" class="header-anchor">#</a> bootstrap.yml介绍</h3> <ul><li>bootstrap.yml比application.yml具有更高的优先级。</li> <li>bootstrap.yml是系统级的资源配置项，application.yml是用户级的资源配置项。</li> <li>SpringCloud会创建&quot;BootStrap Context&quot;作为&quot;ApplicationContext&quot;的==父上下文==。初始化的时候BootStrap Context负责从外部源加载配置属性并解析。这两个上下文共享一个&quot;Environment&quot;，BootStrap 具有更高优先级，他们不会被本地配置覆盖。</li></ul> <h3 id="客户端的配置与测试"><a href="#客户端的配置与测试" class="header-anchor">#</a> 客户端的配置与测试</h3> <p>介绍：客户端主要是在==加载时==通过config server服务端获得github配置仓库的地址，进而通过目标配置文件的文件名获取相应的配置，最后将取得的配置对自身资源进行赋值并提供访问</p> <h4 id="实现过程"><a href="#实现过程" class="header-anchor">#</a> 实现过程</h4> <p>1.创建远程配置yml文件并上传到github上。如下测试案例因为需要进行测试，所以配置了两个profiles方便切换并观察</p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span> 
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> 
        <span class="token key atrule">active</span><span class="token punctuation">:</span>
           <span class="token punctuation">-</span> dev
<span class="token punctuation">---</span>
<span class="token key atrule">server</span><span class="token punctuation">:</span> 
    <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8201</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> dev
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>config<span class="token punctuation">-</span>client<span class="token punctuation">-</span>dev
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
    <span class="token key atrule">client</span><span class="token punctuation">:</span> 
        <span class="token key atrule">service-url</span><span class="token punctuation">:</span> 
            <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka<span class="token punctuation">-</span>dev.com<span class="token punctuation">:</span>7001/eureka/
<span class="token punctuation">---</span>
<span class="token key atrule">server</span><span class="token punctuation">:</span> 
    <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8202</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> test
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>config<span class="token punctuation">-</span>client<span class="token punctuation">-</span>test
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
    <span class="token key atrule">client</span><span class="token punctuation">:</span> 
        <span class="token key atrule">service-url</span><span class="token punctuation">:</span> 
            <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka<span class="token punctuation">-</span>dev.com<span class="token punctuation">:</span>7001/eureka/
</code></pre></div><ol start="2"><li>本地创建config client模块，并配置好pom.xml，以下本组件是必选依赖</li></ol> <div class="language-xml extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="3"><li>编写bootstrap.yml配置文件，这个步骤比较关键，主要是根据此处的配置信息去寻找config server以获得github仓库地址和配置中的目标配置文件文件名</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">cloud</span><span class="token punctuation">:</span>
    <span class="token key atrule">config</span><span class="token punctuation">:</span>
      <span class="token key atrule">name</span><span class="token punctuation">:</span> application_config <span class="token comment">#需要从github上读取的资源名称，注意没有yml后缀名</span>
      <span class="token key atrule">profile</span><span class="token punctuation">:</span> test   <span class="token comment">#本次访问的配置项</span>
      <span class="token key atrule">label</span><span class="token punctuation">:</span> master
      <span class="token key atrule">uri</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//config3344.com<span class="token punctuation">:</span><span class="token number">3344</span>  <span class="token comment">#本微服务启动后先去找3344号服务，通过SpringCloudConfig获取GitHub的服务地址</span>
</code></pre></div><ol start="4"><li>application.yml文件在本module中其实是可写可不写的，为了习惯需要，还是给他写了个名字</li></ol> <div class="language-YML extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud_config
</code></pre></div><ol start="5"><li>修改host文件增加映射，和3344一样</li> <li>编写主启动类，没什么特别的，最基本的主启动类</li> <li>编写controller，此步骤也比较关键，主要是利用@Value注解赋值，若写错了bootstrap.yml中的配置文件名称而没有获取到配置，启动时这里会抛出异常。@Value中注解的参数即是目标配置文件中的参数值，使用El表达式获取</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token annotation punctuation">@org</span><span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>bind<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span><span class="token class-name">RestController</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">RestController</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">&quot;${server.port}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> port<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">&quot;${eureka.client.service-url.defaultZone}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> eurekaZone<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">&quot;${spring.application.name}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>


    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/config&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&quot;RestController{&quot;</span> <span class="token operator">+</span>
                <span class="token string">&quot;port='&quot;</span> <span class="token operator">+</span> port <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
                <span class="token string">&quot;, eurekaZone='&quot;</span> <span class="token operator">+</span> eurekaZone <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
                <span class="token string">&quot;, name='&quot;</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
                <span class="token string">'}'</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="8"><li>先启动config server服务，然后再启用本client服务，根据profiles的值访问对应的端口即可。如本例选择的是test，则访问端口为：http://config3355.com:8202/config。（config3355.com为hosts文件中配置了的映射）</li></ol> <h3 id="springcloud的配置实战"><a href="#springcloud的配置实战" class="header-anchor">#</a> SpringCloud的配置实战</h3> <p>介绍：其实前面client的配置案例都是帮助理解这个组件为主，并没有很大的实际意义。。。。。。这节的案例中是配置一个Provider，一个eureka，他们的配置统一在github上获取，实现统一配置分布式管理和多环境变更，这个才比较有实战意义。</p> <h4 id="实现过程-2"><a href="#实现过程-2" class="header-anchor">#</a> 实现过程</h4> <ol><li>先写好provider和Eureka的配置yml文件，这两个文件和平常配置没什么不同，因为这里主要是说config，所以就没有配置集群，上传yml到github</li></ol> <p>Eureka配置文件示例：</p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span> 
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> 
        <span class="token key atrule">active</span><span class="token punctuation">:</span>
           <span class="token punctuation">-</span> dev
<span class="token punctuation">---</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> dev
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>eureka<span class="token punctuation">-</span>client<span class="token punctuation">-</span>dev
<span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">7001</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> eureka7001.com    <span class="token comment">#hostname为hosts文件中映射的地址</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">register-with-eureka</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>     <span class="token comment">#false表示不向注册中心注册自己</span>
    <span class="token key atrule">fetch-registry</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>           <span class="token comment">#false表示自己就是注册中心，职责是维护实例，不参加检索</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/   <span class="token comment">#设置eureka server的交互地址</span>

<span class="token punctuation">---</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> test
    <span class="token key atrule">application</span><span class="token punctuation">:</span>
        <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>eureka<span class="token punctuation">-</span>client<span class="token punctuation">-</span>dev
<span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">7001</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> eureka7001.com    <span class="token comment">#hostname为hosts文件中映射的地址</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">register-with-eureka</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>     <span class="token comment">#false表示不向注册中心注册自己</span>
    <span class="token key atrule">fetch-registry</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>           <span class="token comment">#false表示自己就是注册中心，职责是维护实例，不参加检索</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/    <span class="token comment">#设置eureka server的交互地址</span>
</code></pre></div><p>Provider配置文件示例：</p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span> 
    <span class="token key atrule">profiles</span><span class="token punctuation">:</span> 
        <span class="token key atrule">active</span><span class="token punctuation">:</span>
           <span class="token punctuation">-</span> dev
<span class="token punctuation">---</span>
<span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8001</span>

<span class="token key atrule">mybatis</span><span class="token punctuation">:</span>
  <span class="token key atrule">config-location</span><span class="token punctuation">:</span> classpath<span class="token punctuation">:</span>mybatis/mybatis.cfg.xml
  <span class="token key atrule">type-aliases-package</span><span class="token punctuation">:</span> com.XXX.entity
  <span class="token key atrule">mapper-locations</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> classpath<span class="token punctuation">:</span>mybatis/mapper/<span class="token important">**/*.xml</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">profiles</span><span class="token punctuation">:</span> dev
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>dept   <span class="token comment">#为这个服务取名，非常重要！！！！！</span>
  <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> com.alibaba.druid.pool.DruidDataSource
    <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> org.gjt.mm.mysql.Driver
    <span class="token key atrule">url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//192.168.88.246<span class="token punctuation">:</span>3306/cloudDB01
    <span class="token key atrule">username</span><span class="token punctuation">:</span> root
    <span class="token key atrule">password</span><span class="token punctuation">:</span> <span class="token number">123456</span>
    <span class="token key atrule">dbcp2</span><span class="token punctuation">:</span>
      <span class="token key atrule">min-idle</span><span class="token punctuation">:</span> <span class="token number">5</span>         <span class="token comment">#最小连接数</span>
      <span class="token key atrule">initial-size</span><span class="token punctuation">:</span> <span class="token number">5</span>    <span class="token comment">#初始化连接数</span>
      <span class="token key atrule">max-total</span><span class="token punctuation">:</span> <span class="token number">10</span>      <span class="token comment">#最大连接数</span>
      <span class="token key atrule">max-wait-millis</span><span class="token punctuation">:</span> <span class="token number">200</span>  <span class="token comment">#等待连接最长的超时时间</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">instance-id</span><span class="token punctuation">:</span> dept8001
    <span class="token key atrule">prefer-ip-address</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
<span class="token punctuation">---</span>
<span class="token key atrule">server</span><span class="token punctuation">:</span>
  <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8001</span>

<span class="token key atrule">mybatis</span><span class="token punctuation">:</span>
  <span class="token key atrule">config-location</span><span class="token punctuation">:</span> classpath<span class="token punctuation">:</span>mybatis/mybatis.cfg.xml
  <span class="token key atrule">type-aliases-package</span><span class="token punctuation">:</span> com.XXX.entity
  <span class="token key atrule">mapper-locations</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> classpath<span class="token punctuation">:</span>mybatis/mapper/<span class="token important">**/*.xml</span>
<span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">profiles</span><span class="token punctuation">:</span> test
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud<span class="token punctuation">-</span>dept   <span class="token comment">#为这个服务取名，非常重要！！！！！</span>
  <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> com.alibaba.druid.pool.DruidDataSource
    <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> org.gjt.mm.mysql.Driver
    <span class="token key atrule">url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//192.168.88.246<span class="token punctuation">:</span>3306/cloudDB02
    <span class="token key atrule">username</span><span class="token punctuation">:</span> root
    <span class="token key atrule">password</span><span class="token punctuation">:</span> <span class="token number">123456</span>
    <span class="token key atrule">dbcp2</span><span class="token punctuation">:</span>
      <span class="token key atrule">min-idle</span><span class="token punctuation">:</span> <span class="token number">5</span>         <span class="token comment">#最小连接数</span>
      <span class="token key atrule">initial-size</span><span class="token punctuation">:</span> <span class="token number">5</span>    <span class="token comment">#初始化连接数</span>
      <span class="token key atrule">max-total</span><span class="token punctuation">:</span> <span class="token number">10</span>      <span class="token comment">#最大连接数</span>
      <span class="token key atrule">max-wait-millis</span><span class="token punctuation">:</span> <span class="token number">200</span>  <span class="token comment">#等待连接最长的超时时间</span>
<span class="token key atrule">eureka</span><span class="token punctuation">:</span>
  <span class="token key atrule">client</span><span class="token punctuation">:</span>
    <span class="token key atrule">service-url</span><span class="token punctuation">:</span>
      <span class="token key atrule">defaultZone</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//eureka7001.com<span class="token punctuation">:</span>7001/eureka/
  <span class="token key atrule">instance</span><span class="token punctuation">:</span>
    <span class="token key atrule">instance-id</span><span class="token punctuation">:</span> dept8001
    <span class="token key atrule">prefer-ip-address</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
</code></pre></div><ol start="2"><li>新开eureka和provide的模块并在pom.xml中添加依赖，其他必要依赖和之前的案例一样，但是config的依赖一定要添加上</li></ol> <div class="language-XML extra-class"><pre class="language-xml"><code>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-config<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="3"><li>两个模块都要编写bootstrap.yml文件，和上面的案例一样</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">cloud</span><span class="token punctuation">:</span>
    <span class="token key atrule">config</span><span class="token punctuation">:</span>
      <span class="token key atrule">name</span><span class="token punctuation">:</span> application_config <span class="token comment">#需要从github上读取的资源名称，注意没有yml后缀名</span>
      <span class="token key atrule">profile</span><span class="token punctuation">:</span> test   <span class="token comment">#本次访问的配置项</span>
      <span class="token key atrule">label</span><span class="token punctuation">:</span> master
      <span class="token key atrule">uri</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//config3344.com<span class="token punctuation">:</span><span class="token number">3344</span>  <span class="token comment">#本微服务启动后先去找3344号服务，通过SpringCloudConfig获取GitHub的服务地址</span>
</code></pre></div><ol start="4"><li>(可选)两个模块中编写application.yml文件，可以配置一下服务名</li></ol> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">application</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> microservicecloud_config
</code></pre></div><ol start="5"><li>两个模块的主启动类，Eureka的正常加EurekaServer注解，Provider加EurekaClient注解，不详述</li> <li>编写Provider模块的业务代码</li> <li>启动测试，因为这两个模块都要通过3344ConfigServer为其在github上获取配置，所以要先启动3344模块，然后再一次启动eureka和provider模块，进行测试即可。</li></ol></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-db14854a data-v-db14854a><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-db14854a><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-db14854a></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-db14854a></path></svg></div><!----></div></div>
    <script src="/assets/js/app.447d4224.js" defer></script><script src="/assets/js/3.9d76740c.js" defer></script><script src="/assets/js/1.c4fd7d2e.js" defer></script><script src="/assets/js/90.5202da0a.js" defer></script>
  </body>
</html>
